package com.easyOrder.service.material;

import com.easyOrder.core.comm.BeanMapper;
import com.easyOrder.dao.MaterialMapper;
import com.easyOrder.dto.MaterialClassDTO;
import com.easyOrder.dto.TagDTO;
import com.easyOrder.model.Material;
import com.easyOrder.model.MaterialClass;
import com.easyOrder.model.MaterialExample;
import com.easyOrder.service.enums.MaterialState;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkArgument;

/**
 * Created by liutao on 2017/7/17.
 */
@Service
public class MaterialService {

    @Autowired
    private MaterialClassService materialClassService;

    @Autowired
    private MaterialMapper materialMapper;

    public TagDTO findAllByBranchId(Long branchId, Long tag) {
        TagDTO tagDTO = new TagDTO();
        tagDTO.setTag(tag);
        List<MaterialClass> materialClasses = materialClassService.findValidClassByBranchId(branchId);
        if (CollectionUtils.isEmpty(materialClasses)) {
            tagDTO.setMaterialClassDTOS(Lists.newArrayList());
            return tagDTO;
        }
        Set<Long> classIds = materialClasses.stream().map(materialClasse -> materialClasse.getId()).collect(Collectors.toSet());

        MaterialExample example = new MaterialExample();
        example.createCriteria().andClassIdIn(Lists.newArrayList(classIds)).andStatusIdEqualTo(MaterialState.normal.getValue());
        List<Material> materials = materialMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(materials)) {
            tagDTO.setMaterialClassDTOS(Lists.newArrayList());
            return tagDTO;
        }

        Map<Long, List<Material>> map = BeanMapper.toMapList(materials, Material::getClassId);
        List<MaterialClassDTO> materialClassDTOS = BeanMapper.mapList(materialClasses, MaterialClassDTO.class);

        for (int i = 0; i < materialClassDTOS.size(); i++) {
            MaterialClassDTO materialClassDTO = materialClassDTOS.get(i);
            List<Material> list = map.get(materialClassDTO.getId());
            if (CollectionUtils.isNotEmpty(list)) {
                materialClassDTO.setMaterials(list);
            } else {
                materialClassDTOS.remove(materialClassDTO);
                i--;
            }
        }

        tagDTO.setMaterialClassDTOS(materialClassDTOS);
        return tagDTO;
    }

    public Map<Long, Material> buildValidMapByIds(Collection<Long> materialIds) {
        return findValidMaterialByIds(materialIds).stream()
                .collect(Collectors.toMap(Material::getId, Function.identity()));
    }

    public List<Material> findValidMaterialByIds(Collection<Long> materialIds) {
        if (CollectionUtils.isEmpty(materialIds)) {
            return Collections.emptyList();
        }
        MaterialExample example = new MaterialExample();
        example.createCriteria().andIdIn(Lists.newArrayList(materialIds))
                .andStatusIdEqualTo(MaterialState.normal.getValue())
                .andQuantityOfResidueGreaterThan(BigDecimal.ZERO);
        return materialMapper.selectByExample(example);
    }

    public List<Material> findByIds(Collection<Long> materialIds) {
        MaterialExample example = new MaterialExample();
        example.createCriteria().andIdIn(Lists.newArrayList(materialIds));
        return materialMapper.selectByExample(example);
    }

    public void checkInvalidMaterials(Set<Long> materialIds, Map<Long, BigDecimal> map) {
        Map<Long, Material> validMaterialMap = buildValidMapByIds(materialIds);
        Set<String> invalidMaterialNames = Sets.newHashSet();
        Set<Long> invalidMaterialIds = Sets.newHashSet();
        materialIds.forEach(id -> {
            if (!validMaterialMap.containsKey(id)) {
                invalidMaterialIds.add(id);
            } else if (validMaterialMap.get(id).getQuantityOfResidue().doubleValue() < map.get(id).doubleValue()) {
                invalidMaterialIds.add(id);
            }
        });
        if (CollectionUtils.isNotEmpty(invalidMaterialIds)) {
            List<Material> materialList = findByIds(invalidMaterialIds);
            materialList.forEach(m -> {
                invalidMaterialNames.add(m.getName());
            });
        }
        checkArgument(CollectionUtils.isEmpty(invalidMaterialNames),
                MessageFormat.format("{0}数量不足,请选择其他商品", StringUtils.join(invalidMaterialNames, ",")));


    }

    public void updateMaterial(Material material) {
        materialMapper.updateByPrimaryKeySelective(material);
    }
}
